/*
 * Copyright 2008 Zoundry LLC, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.zoundry.gaedt.core.codegen;

import java.io.InputStream;
import java.text.MessageFormat;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.zoundry.gaedt.core.ZGaeException;
import org.zoundry.gaedt.core.models.cspec.ZGaeControllerModel;
import org.zoundry.gaedt.core.models.cspec.ZGaeControllersModel;
import org.zoundry.gaedt.core.util.ZGaeResourceUtil;
import org.zoundry.gaedt.core.util.ZGaeUTF8Util;
import org.zoundry.gaedt.core.util.ZGaeUtil;


/**
 * This class accepts a .cspec model and generates python code from it.
 */
public class ZGaeCSpecToPythonGenerator implements IZGaeCodeGenerator
{
    private static final String sTemplate = loadTemplate();

    /**
     * Loads the template.
     */
    private static String loadTemplate()
    {
        InputStream iStream = ZGaeCSpecToPythonGenerator.class.getResourceAsStream("cspecToPy.template");
        try
        {
            return ZGaeResourceUtil.getContents(iStream, ZGaeUTF8Util.UTF8_ENCODING);
        }
        catch (ZGaeException e)
        {
            ZGaeUtil.logError(e);
            return null;
        }
    }

    /**
     * Generates python code from a .cspec model.
     *
     * @param aCSpecModel
     */
    public String generate(ZGaeControllersModel aCSpecModel)
    {
        String imports = generateImports(aCSpecModel).trim();
        String debugFlag = generateDebugFlag(aCSpecModel).trim();
        String controllers = generateControllers(aCSpecModel).trim();

        return MessageFormat.format(sTemplate, imports, debugFlag, controllers);
    }

    /**
     * Generate the imports section of the python file.
     *
     * @param aSpecModel
     */
    private String generateImports(ZGaeControllersModel aCSpecModel)
    {
        Set<String> imports = new LinkedHashSet<String>();

        List<ZGaeControllerModel> controllers = aCSpecModel.getControllers();
        for (ZGaeControllerModel controller : controllers)
        {
            int lastIndexOf = controller.getClassname().lastIndexOf('.');
            String packagename = controller.getClassname().substring(0, lastIndexOf);
            String classname = controller.getClassname().substring(lastIndexOf + 1);
            String line = MessageFormat.format("from {0} import {1}", packagename, classname);
            imports.add(line);
        }

        StringBuffer buffer = new StringBuffer();
        synchronized (buffer)
        {
            for (String pyimport : imports)
            {
                buffer.append(pyimport);
                buffer.append("\r\n");
            }

            return buffer.toString();
        }
    }

    /**
     * Generates the debug flag: True/False.
     *
     * @param aCSpecModel
     */
    private String generateDebugFlag(ZGaeControllersModel aCSpecModel)
    {
        return aCSpecModel.isDebug() ? "True" : "False";
    }

    /**
     * Generates the controllers section of the python file.
     *
     * @param aCSpecModel
     */
    private String generateControllers(ZGaeControllersModel aCSpecModel)
    {
        StringBuffer buffer = new StringBuffer();
        synchronized (buffer)
        {
            List<ZGaeControllerModel> controllers = aCSpecModel.getControllers();
            boolean isFirst = true;
            for (ZGaeControllerModel controller : controllers)
            {
                String classname = controller.getClassname().substring(controller.getClassname().lastIndexOf('.') + 1);
                String line = null;
                if (controller.getPattern() != null)
                    line = MessageFormat.format("        (r\"{0}\", {1})", controller.getPattern(), classname);
                else
                    line = MessageFormat.format("        (\"{0}\", {1})", controller.getPath(), classname);

                if (!isFirst)
                    buffer.append(",");
                else
                    isFirst = false;
                buffer.append("\r\n");
                buffer.append(line);
            }

            return buffer.toString();
        }
    }
}
